#include "../include/line.h"
#include "../include/prototype.h"
#include "../include/closure.h"
#include "../include/queue.h"
#include "../include/map.h"
#include "../include/chunk.h"

// TValue R(Closure *self, _int index)
// {
//     TValue result = self->virtualRegister[index];
//     if (IS_UPVALUE(result))
//     {
//         return *result.value.upvalue->value;
//     }
//     return result;
// }

// TValue C(Closure *self, _int index)
// {
//     return self->prototype->chunk->constants[~index];
// }

// TValue RC(Closure *self, _int index)
// {
//     if (index > 0)
//         return R(self, index);
//     else
//         return C(self, index);
// }

// TValue SR(Closure *self, _int index, TValue value)
// {
//     self->virtualRegister[index] = value;
// }

// void SRU(Closure *self, _int index, TValue value)
// {
//     if (IS_UPVALUE(self->virtualRegister[index]))
//     {
//         *(self->virtualRegister[index].value.upvalue->value) = value;
//     }
//     else
//     {
//         self->virtualRegister[index] = value;
//     }
// }

void Line_Init(Line *line)
{
    Collector_Init(line, &line->collector);
    Array_Init(&line->closure_stack, Closure);
    Array_Init(&line->value_stack, TValue);
    line->exception = (Exception){TNULL, TNULL};
    Map_Init(&line->packages, 32);
}

// Exception *Line_DoFile(Line *line, const _byte *path)
// {
//     // Scanner scanner;
//     // Scanner_Init(line, &scanner);
//     // Exception *exception = Scanner_ParseFile(&scanner, path);
//     // if (exception == NULL)
//     // {
//     //     Scanner_Print(&scanner);
//     //     Constructor constructor;
//     //     Constructor_Init(&constructor, &scanner);
//     //     exception = Constructor_Parser(&constructor);
//     //     if (exception == NULL)
//     //     {
//     //         Translator translator;
//     //         Translator_Init(&translator, &constructor);
//     //         Translate_Parse(&translator);
//     //         Chunk *chunk = translator.result;
//     //     }
//     //     return exception;
//     // }

//     // TValue_Print(&exception->value);
// }

// void Line_Start(Line *line)
// {
//     TValue result = TNULL;
//     while (line->stack.length != 0)
//     {
//         Closure *closuer = &Array_Peek(&line->stack, Closure);
//         if (closuer->cursor < closuer->prototype->numOfInstructions)
//         {
//             Instruction *instruction = &closuer->prototype->instructions[closuer->cursor];
//             switch (instruction->category)
//             {
//             case VM_LOAD:
//             {
//                 SR(closuer, instruction->args[0], closuer->virtualRegister[instruction->args[1]]);
//                 break;
//             }
//             case VM_MAP:
//             {
//                 Object *map = Map_New(line);
//                 closuer->virtualRegister[instruction->args[0]] = (TValue){T_MAP, {.object = map}};
//                 break;
//             }
//             case VM_QUEUE:
//             {
//                 Object *array = Queue_New(line);
//                 closuer->virtualRegister[instruction->args[0]] = (TValue){T_MAP, {.object = array}};
//                 break;
//             }
//             case VM_GETV:
//             {
//                 break;
//             }
//             case VM_SETV:
//             {
//                 break;
//             }
//             case VM_POS:
//             {

//                 break;
//             }
//             case VM_NEG:
//             {

//                 break;
//             }
//             case VM_ADD:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 TValue *left = GetTValue(closuer, instruction->args[1]);
//                 TValue *right = GetTValue(closuer, instruction->args[2]);
//                 switch (left->category)
//                 {
//                 case T_INTEGER:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->category = T_INTEGER;
//                         value->value.integer = left->value.integer + right->value.integer;
//                     }
//                     else
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = left->value.integer + right->value.decimal;
//                     }
//                     break;
//                 case T_DECIMAL:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = left->value.decimal + right->value.integer;
//                     }
//                     else
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = left->value.decimal + right->value.decimal;
//                     }
//                     break;
//                 }
//                 break;
//             }
//             case VM_SUB:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 TValue *left = GetTValue(closuer, instruction->args[1]);
//                 TValue *right = GetTValue(closuer, instruction->args[2]);
//                 switch (left->category)
//                 {
//                 case T_INTEGER:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->category = T_INTEGER;
//                         value->value.integer = left->value.integer - right->value.integer;
//                     }
//                     else
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = left->value.integer - right->value.decimal;
//                     }
//                     break;
//                 case T_DECIMAL:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = left->value.decimal - right->value.integer;
//                     }
//                     else
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = left->value.decimal - right->value.decimal;
//                     }
//                     break;
//                 }
//                 break;
//             }
//             case VM_MUL:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 TValue *left = GetTValue(closuer, instruction->args[1]);
//                 TValue *right = GetTValue(closuer, instruction->args[2]);
//                 switch (left->category)
//                 {
//                 case T_INTEGER:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->category = T_INTEGER;
//                         value->value.integer = left->value.integer * right->value.integer;
//                     }
//                     else
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = left->value.integer * right->value.decimal;
//                     }
//                     break;
//                 case T_DECIMAL:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = left->value.decimal * right->value.integer;
//                     }
//                     else
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = left->value.decimal * right->value.decimal;
//                     }
//                     break;
//                 }
//                 break;
//             }
//             case VM_DIV:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 TValue *left = GetTValue(closuer, instruction->args[1]);
//                 TValue *right = GetTValue(closuer, instruction->args[2]);
//                 if (right->value.integer == 0)
//                 {
//                     // Line_Throw(line,"除数不能为0",TNULL);
//                 }
//                 value->category = T_DECIMAL;
//                 switch (left->category)
//                 {
//                 case T_INTEGER:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->value.integer = (double)left->value.integer / (double)right->value.integer;
//                     }
//                     else
//                     {
//                         value->value.decimal = (double)left->value.integer / right->value.decimal;
//                     }
//                     break;
//                 case T_DECIMAL:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->value.decimal = left->value.decimal / (double)right->value.integer;
//                     }
//                     else
//                     {
//                         value->value.decimal = left->value.decimal / right->value.decimal;
//                     }
//                     break;
//                 }
//                 break;
//             }
//             case VM_MOD:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 value->category = T_INTEGER;
//                 TValue *left = GetTValue(closuer, instruction->args[1]);
//                 TValue *right = GetTValue(closuer, instruction->args[2]);
//                 switch (left->category)
//                 {
//                 case T_INTEGER:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->value.integer = left->value.integer % right->value.integer;
//                     }
//                     else
//                     {
//                         value->value.decimal = left->value.integer % (long long)right->value.decimal;
//                     }
//                     break;
//                 case T_DECIMAL:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->value.decimal = (long long)left->value.decimal % right->value.integer;
//                     }
//                     else
//                     {
//                         value->value.decimal = (long long)left->value.decimal % (long long)right->value.decimal;
//                     }
//                     break;
//                 }
//                 break;
//             }
//             case VM_POWER:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 TValue *left = GetTValue(closuer, instruction->args[1]);
//                 TValue *right = GetTValue(closuer, instruction->args[2]);
//                 switch (left->category)
//                 {
//                 case T_INTEGER:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->category = T_INTEGER;
//                         value->value.integer = pow(left->value.integer, right->value.integer);
//                     }
//                     else
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = pow(left->value.integer, right->value.decimal);
//                     }
//                     break;
//                 case T_DECIMAL:
//                     if (right->category == T_INTEGER)
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = pow(left->value.decimal, right->value.integer);
//                     }
//                     else
//                     {
//                         value->category = T_DECIMAL;
//                         value->value.decimal = pow(left->value.decimal, right->value.decimal);
//                     }
//                     break;
//                 }
//                 break;
//             }
//             case VM_UNM:
//             {
//                 break;
//             }
//             case VM_NOT:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 value->category = T_BOOLEAN;
//                 TValue *arg1 = GetTValue(closuer, instruction->args[1]);
//                 value->value.boolean = !arg1->value.boolean;
//                 break;
//             }
//             case VM_EQ:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 value->category = T_BOOLEAN;
//                 TValue *left = GetTValue(closuer, instruction->args[1]);
//                 TValue *right = GetTValue(closuer, instruction->args[2]);
//                 value->value.boolean = Value_Equals(left, right);
//                 break;
//             }
//             case VM_NEQ:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 value->category = T_BOOLEAN;
//                 TValue *left = GetTValue(closuer, instruction->args[1]);
//                 TValue *right = GetTValue(closuer, instruction->args[2]);
//                 value->value.boolean = !Value_Equals(left, right);
//                 break;
//             }
//             case VM_LE:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 value->category = T_BOOLEAN;
//                 TValue *left = GetTValue(closuer, instruction->args[1]);
//                 TValue *right = GetTValue(closuer, instruction->args[2]);
//                 switch (left->category)
//                 {
//                 case T_INTEGER:
//                     if (right->category == T_DECIMAL)
//                         value->value.boolean = left->value.integer <= right->value.decimal;
//                     else
//                         value->value.boolean = left->value.integer <= right->value.integer;
//                     break;
//                 case T_DECIMAL:
//                     if (right->category == T_DECIMAL)
//                         value->value.boolean = left->value.decimal <= right->value.decimal;
//                     else
//                         value->value.boolean = left->value.decimal <= right->value.integer;
//                     break;
//                 }
//                 break;
//                 ;
//             }
//             case VM_LT:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 value->category = T_BOOLEAN;
//                 TValue *left = GetTValue(closuer, instruction->args[1]);
//                 TValue *right = GetTValue(closuer, instruction->args[2]);
//                 switch (left->category)
//                 {
//                 case T_INTEGER:
//                     if (right->category == T_DECIMAL)
//                         value->value.boolean = left->value.integer < right->value.decimal;
//                     else
//                         value->value.boolean = left->value.integer < right->value.integer;
//                     break;
//                 case T_DECIMAL:
//                     if (right->category == T_DECIMAL)
//                         value->value.boolean = left->value.decimal < right->value.decimal;
//                     else
//                         value->value.boolean = left->value.decimal < right->value.integer;
//                     break;
//                 }
//                 break;
//             }
//             case VM_AND:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 value->category = T_BOOLEAN;
//                 value->value.boolean = GetTValue(closuer, instruction->args[1])->value.boolean && GetTValue(closuer, instruction->args[2])->value.boolean;
//                 break;
//             }
//             case VM_OR:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 value->category = T_BOOLEAN;
//                 value->value.boolean = GetTValue(closuer, instruction->args[1])->value.boolean || GetTValue(closuer, instruction->args[2])->value.boolean;
//                 break;
//             }
//             case VM_JUMP:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 if (value->value.boolean == instruction->args[1])
//                 {
//                     closuer->cursor = instruction->args[2] - 1;
//                 }
//                 break;
//             }
//             case VM_GOTO:
//             {
//                 closuer->cursor = instruction->args[0] - 1;
//                 break;
//             }
//             case VM_CONCAT:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 value->category = T_STRING;
//                 String *left = (String *)GetTValue(closuer, instruction->args[1])->value.object;
//                 String *right = (String *)GetTValue(closuer, instruction->args[2])->value.object;
//                 // value->value.object = String_New_Concat(line, left, right);
//                 break;
//             }
//             case VM_RETURN:
//             {
//                 break;
//             }
//             case VM_CALL:
//             {
//                 break;
//             }
//             case VM_IMPORT:
//             {
//                 break;
//             }
//             case VM_CLOSURE:
//             {

//                 break;
//             }
//             case VM_GETUPVAL:
//             {
//                 Upvalue *upvalue = NULL;
//                 if (closuer->upvalue[instruction->args[1]] != NULL)
//                 {
//                     UpvalueDescribe describe = closuer->prototype->upvalueDescribes[instruction->args[1]];
//                     Upvalue *upvalue = Globe_Malloc(sizeof(Upvalue));
//                     Upvalue_Init(line, upvalue);
//                     line->root = upvalue;
//                     closuer->upvalues[instruction->args[1]] = upvalue;
//                 }
//                 TValue *value = GetTValue(closuer, instruction->args[0]);
//                 *value = *upvalue->value;
//                 break;
//             }
//             case VM_SETUPVAL:
//             {
//                 Upvalue *upvalue = NULL;
//                 if (closuer->upvalues[instruction->args[0]] != NULL)
//                 {
//                     UpvalueDescribe describe = closuer->prototype->upvalueDescribes[instruction->args[1]];
//                     Upvalue *upvalue = Pool_Malloc(sizeof(Upvalue));
//                     Upvalue_Init(line, upvalue);
//                     line->root = upvalue;
//                     closuer->upvalues[instruction->args[0]] = upvalue;
//                 }
//                 TValue *value = GetTValue(closuer, instruction->args[1]);
//                 *value = *upvalue->value;
//                 break;
//             }
//             case VM_LOOP:
//             {
//                 break;
//             }
//             case VM_PRINT:
//             {
//                 TValue *value = GetTValue(closuer, instruction->args[0]);

//                 break;
//             }
//             }
//             closuer->cursor++;
//         }
//         else
//         {
//             closuer = &T_ARRAY_POP(&line->stack);
//             result = closuer->result;
//         }
//     }
// }